using Dm.util;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Process.Application;
using Process.Application.Services;
using Process.Application.WorkflowDefintion;
using Process.Domain.DTO.InputDTO;
using Process.Domain.DTO.InputDTO.Audit;
using Process.Domain.DTO.OutDTO;
using Process.Domain.Entities;
using Process.Infrastructure.Repositories;
using Process.Result;
using Produce.Application.Services;
using Produce.Domain.Entities;
using Produce.Infrastructure.Repositories;
using System.Text.Json;
using System.Threading.Tasks;
using WorkflowCore.Interface;
using WorkflowCore.Models;
using WorkflowCore.Services;
using Yitter.IdGenerator;
using static Process.Application.Services.ProcessFlowSorter;



namespace Process.Api.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class OperationModelController : ControllerBase
    {
        private readonly IOperationAppService<OperationModel> _operationModelAppService;
        private readonly IProcessRepository<OperationModel> _operationRepository;
        private readonly IWrokflowDefintion _wrokflowDefintion;
        private readonly IProduceModelRepository<ProductionWorkorder> _produceModelRepository;
        private readonly IWorkflowHost _workflowHost;
        private readonly IProcessRepository<ProcessAuditModel> _processaudityModel;

        public OperationModelController(
            IOperationAppService<OperationModel> operationModelAppService,
            IProcessRepository<OperationModel> operationRepository,
            IWrokflowDefintion wrokflowDefintion,
              IProduceModelRepository<ProductionWorkorder> produceModelRepository, IWorkflowHost workflowHost, IProcessRepository<ProcessAuditModel> processaudityModel)
        { 
            _operationModelAppService = operationModelAppService;
            _operationRepository = operationRepository;
            _wrokflowDefintion = wrokflowDefintion;
            _produceModelRepository = produceModelRepository;
            _workflowHost = workflowHost;
            _processaudityModel = processaudityModel;
            
        }

        /// <summary>
        /// 添加工艺
        /// </summary>
        /// <param name="operationDTO">工艺数据传输对象</param>
        /// <returns>API结果</returns>
        [HttpPost]
        public ApiResult<int> AddOperationModel(AddOperationDTO operationDTO)
        {
            // 直接调用业务层方法，业务逻辑由业务层处理
            return _operationModelAppService.AddOperation(operationDTO);
        }

        /// <summary>
        /// 查询工艺
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns>封装响应类</returns>
        [HttpGet]
        public Apipaging<PagingOperationDTO> ShowOperation([FromQuery] PagingOperationInput input)
        {
            return _operationModelAppService.PagingOperation(input);
        }

        /// <summary>
        /// 删除工艺
        /// </summary>
        /// <param name="Id">工艺ID</param>
        /// <returns>封装响应类</returns>
        [HttpDelete]
        public ApiResult<int> DeleteOperationModel(long Id)
        {
            return _operationModelAppService.DeleteOperation(Id);
        }

        /// <summary>
        /// 修改工艺
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns>封装响应类</returns>
        [HttpPost]
        public ApiResult<int> UpdateOperationModel(UpdateOperationInput input)
        {
            return _operationModelAppService.UpdateOperation(input);
        }
        /// <summary>
        /// 显示所有工艺
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ApiResult<List<ShowOperationDTO>> VueShowOperation()
        {
            return _operationModelAppService.ShowOperation();
        }

        /// <summary>
        /// 排序工艺流程并更新工艺的Steps字段
        /// </summary>
        /// <param name="workflow">工艺流程输入</param>
        /// <returns>操作结果，1表示成功，2表示失败</returns>
        [HttpPost]
        public ApiResult<int> SortProcessFlowProcess(WorkflowSortInput workflow)
        {
            try
            {
                // 1. 调用工艺流程排序工具对流程进行排序
               List<StepNode> sortedWorkflow = ProcessFlowSorter.SortWorkflow(workflow);

                // 2. 根据WorkflowSortInput.Id查询对应的工艺记录
                // 将string Id转换为long类型
                long.TryParse(workflow.operationid.toString(), out long operationIdLong);
                
                   
                
                
                // 直接使用仓储查询工艺实体
                var operation = _operationRepository.GetModel(operationIdLong);

                if (operation == null)
                { 
                    return new ApiResult<int>()
                    {
                        Success = ResultCode.Error,
                        Message = "未找到该工艺"
                    };
                }
               
                
                // 3. 将已排序的工序流程序列化为字符串
                string serializedWorkflow = JsonConvert.SerializeObject(sortedWorkflow, new JsonSerializerSettings 
                { 
                    StringEscapeHandling = StringEscapeHandling.Default,
                    Formatting = Formatting.None
                });


                

                // 4. 将序列化后的工序流程赋值给工艺对象的Steps字段
                operation.Steps = serializedWorkflow;

               
                // 5. 调用仓储的更新方法更新工艺记录
                int result = _operationRepository.Update(operation);
                
                // 6. 根据更新结果返回对应的状态码
                return new ApiResult<int>
                {
                    Success = result > 0 ? ResultCode.Success : ResultCode.Fail,
                    Message = result > 0 ? "工艺流程排序更新成功" : "工艺流程排序更新失败",
                    Data = result > 0 ? 1 : 2
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<int>
                {
                    Success = ResultCode.Fail,
                    Message = $"排序工艺流程失败: {ex.Message}",
                    Data = 2
                };
            }
        }


        /// <summary>
        /// 对工艺流程进行排序并转换为StepNode格式
        /// </summary>
        /// <param name="workflow">工艺流程定义</param>
        /// <returns>排序后的StepNode列表</returns>
        [HttpPost]
        public ApiResult<List<StepNode>> SortOperation([FromBody] WorkflowDefinition workflow)
        {
            try
            {
                var stepNodes = new List<StepNode>();
                var nodeDict = workflow.nodes.ToDictionary(n => n.id, n => n);

                // 构建节点之间的关系图
                var connectionMap = new Dictionary<string, string>();
                foreach (var conn in workflow.connections)
                {
                    connectionMap[conn.source] = conn.target;
                }

                // 创建节点顺序列表，包括开始和结束节点
                var orderedNodes = new List<NodeDefinition>();

                // 添加开始节点（如果存在）
                if (nodeDict.ContainsKey("start"))
                {
                    orderedNodes.Add(nodeDict["start"]);
                }

                // 从开始节点追踪，收集中间所有节点
                string currentNodeId = "start";
                while (currentNodeId != null && connectionMap.ContainsKey(currentNodeId))
                {
                    // 获取下一个节点ID
                    string nextNodeId = connectionMap[currentNodeId];

                    // 如果到达end节点就跳出循环，稍后单独处理end节点
                    if (nextNodeId == "end") break;

                    // 添加中间节点
                    if (nodeDict.ContainsKey(nextNodeId))
                    {
                        orderedNodes.Add(nodeDict[nextNodeId]);
                    }

                    currentNodeId = nextNodeId;
                }

                // 添加结束节点（如果存在）
                if (nodeDict.ContainsKey("end"))
                {
                    orderedNodes.Add(nodeDict["end"]);
                }

                // 创建StepNode对象并设置正确的StepNextId链接
                for (int i = 0; i < orderedNodes.Count; i++)
                {
                    var currentNode = orderedNodes[i];

                    // 确定下一个节点的StepId
                    string nextStepId = "";
                    // 如果不是最后一个节点，则StepNextId为下一个节点的techId
                    if (i < orderedNodes.Count - 1)
                    {
                        nextStepId = orderedNodes[i + 1].techId;
                    }

                    var stepNode = new StepNode
                    {
                        StepId = currentNode.techId,
                        StepName = currentNode.name,
                        StepNextId = nextStepId,
                        AuditUserId = 0,
                        AuditUserName = ""
                    };
                    stepNodes.Add(stepNode);
                    
                }

                // 更新工艺记录的步骤信息
                try
                {
                    long.TryParse(workflow.operationid.ToString(), out long operationIdLong);
                    var operation = _produceModelRepository.GetModel(operationIdLong);
                    if (operation != null)
                    {
                        operation.step = Newtonsoft.Json.JsonConvert.SerializeObject(stepNodes, new Newtonsoft.Json.JsonSerializerSettings { 
                        StringEscapeHandling = Newtonsoft.Json.StringEscapeHandling.Default, 
                        Formatting = Newtonsoft.Json.Formatting.None 
                    });
                        _produceModelRepository.Update(operation);
                    }
                    AddWorkflowDefinitionDTO addWorkflow = new AddWorkflowDefinitionDTO()
                    {
                        DefinitionId = workflow.operationid.ToString(),
                        Title = workflow.name,
                        Steps = stepNodes,
                        Version = Convert.ToInt32(workflow.version.substring(0, 1)),
                    };                   
                    _wrokflowDefintion.AddWorkflowDefinition(addWorkflow);
                  
                }
                catch (Exception ex)
                {
                    // 记录异常，但不中断返回流程
                }

                return new ApiResult<List<StepNode>>
                {
                    Success = ResultCode.Success,
                    Message = "工艺流程排序成功",
                    Data = stepNodes
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<List<StepNode>>
                {
                    Success = ResultCode.Fail,
                    Message = $"工艺流程排序失败: {ex.Message}",
                    Data = null
                };
            }
        }


        /// <summary>
        /// 启动流程
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult<string>> StartWorkflow(long  Id)
        {
            var data = _wrokflowDefintion.StartWorkflow(Id);
            var DefinitionId = data.DefinitionId.toString();
            var Version= data.Version;
           var workflowId= await _workflowHost.StartWorkflow(DefinitionId, Version);
            return new ApiResult<string>()
            {
                Success = ResultCode.Success,
                Message = "流程定义成功",
                Data = $"流程定义成功+{workflowId}+"
            };
        }

        /// <summary>
        /// 审批流程
        /// </summary>
        /// <param name="dto">审批数据</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<string>> AuditProcess(AuditprocessDTO dto)
        {

            var data = _processaudityModel.GetValue().Where(x => x.WorkflowId == dto.WorkflowId && x.Status == "审核中").FirstOrDefault();
            ProcessAuditModel audit = new ProcessAuditModel() {                
                Remark = dto.Remark,
                Status = dto.Status,
                AuditType = dto.AuditType,
                ExecutionPointer= dto.ExecutionPointer,
            };
           
            data.AuditType=audit.AuditType;
            data.Remark=audit.Remark;
            data.Status=audit.Status;
            _processaudityModel.Update(data);
            await _workflowHost.PublishEvent("MyEvent", dto.WorkflowId, dto);
            return new ApiResult<string>()
            {
                Success = ResultCode.Success,
                Message = "审批成功",
                Data = "流程定义成功"
            };
        }


        [HttpGet]
        public async Task<Apipaging<ShowAuditProcessDTO>> ShowAuditProcess([FromQuery] AuditProcess auditProcess)
        {
         var  data= (_wrokflowDefintion.ShowAuditProcess(auditProcess)).PagingData;
            return new Apipaging<ShowAuditProcessDTO>()
            {
                Success = ResultCode.Success,
                Message = "流程定义成功",
                PagingData = data
            };

        }


        [HttpGet]
        public async Task<Apipaging<ShowAuditDataOut>> ShowAuditDataClick([FromQuery] ShowAuditData audit)
        {
            var data = (_wrokflowDefintion.ShowAuditDataClick(audit)).PagingData;
            return new Apipaging<ShowAuditDataOut>()
            {
                Success = ResultCode.Success,
                Message = "流程定义成功",
                PagingData = data
            };
        }
        /// <summary>
        /// 表示流程中的一个步骤节点。
        /// </summary>

        // WorkflowDefinition及相关类定义保持不变
        public class WorkflowDefinition
        {
            public string id { get; set; }
            /// <summary>
            /// 工艺id
            /// </summary>
            public long operationid { get; set; }
            /// <summary>
            /// 版本
            /// </summary>
            public string version { get; set; }
            /// <summary>
            /// 名称
            /// </summary>
            public string name { get; set; }
            /// <summary>
            /// /描述
            /// </summary>
            public string description { get; set; }
            public List<NodeDefinition> nodes { get; set; }
            public List<ConnectionDefinition> connections { get; set; }
        }
        public class NodeDefinition
        {
            public string id { get; set; }
            public string techId { get; set; }
            public string name { get; set; }
            public Position position { get; set; }
            public Dictionary<string, object> parameters { get; set; }
            public string category { get; set; }
        }

        public class ConnectionDefinition
        {
            public string id { get; set; }
            public string source { get; set; }
            public string target { get; set; }
            public Dictionary<string, object> parameters { get; set; }
        }

        public class Position
        {
            public double x { get; set; }
            public double y { get; set; }
        }
    }
} 